package cn.com.callback

import cn.com.elite.EliteBean
import cn.com.elite.Util
import cn.com.kh.KHDBConfig
import cn.com.kh.KHUtil
import com.wisdge.utils.security.sm.cert.SM2CertUtil
import net.sf.json.JSONObject
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import java.util.regex.Pattern
import org.bouncycastle.crypto.digests.SM3Digest
import org.bouncycastle.util.encoders.Hex

/**
 * Staff账号密码校验
 */

public class apiStaffPWDCheck implements ServiceBackInvoke {
    private static final Log log = LogFactory.getLog(apiStaffPWDCheck.class);

    private static String URL;
    private static String APPKEY;
    private String charset = "utf-8"; // 设置字符集
    private int timeout = 100000; // 设置请求超时时间
    private int enableSSLflag = 0;

    public String doCallBack(EliteBean eliteBean, HttpServletRequest request, HttpServletResponse response) {

        long startTime = System.currentTimeMillis();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        String v_interfacetype = request.getParameter("interfacetype");

        JSONObject results = new JSONObject();  //初始化返回参数
        String callJson = "";   //接收客户端调用参数
        InputStreamReader reader = new InputStreamReader(request.getInputStream(), "UTF-8");
        BufferedReader iny = new BufferedReader(reader);
        String line;
        while ((line = iny.readLine()) != null) {
            callJson += line;
        }
        log.info("[调用请求信息]：" + callJson);
        JSONObject inJson = JSONObject.fromObject(callJson);
        log.info("[调用请求信息v_interfacetype类型]：" + v_interfacetype);

        if (v_interfacetype == "check") {
            String token = inJson.getString("token"); //获取token
            results = checkPWDFlag(eliteBean, token);//更新密码
        } else if (v_interfacetype == "update") {
            String token = inJson.getString("token"); //获取token
            String old_password = inJson.getString("old_password"); //获取密码
            String new_password = inJson.getString("new_password"); //获取密码
            String again_password = inJson.getString("again_password"); //获取密码
            results = updatePWD(eliteBean, token, old_password, new_password, again_password); //更新密码
        } else {
            results.put("code", "-1");
            results.put("msg", "interfacetype类型不存在");
        }
        return results.toString();
    }

    /**
     * 校验密码
     */
    public JSONObject checkPWDFlag(EliteBean eliteBean, String token) {
        JSONObject results = new JSONObject();
        //查询staff表中的密码校验标识：0=通过，1=不通过
            List pwdflaglist = eliteBean.chaxun_sql("SELECT s.pwd_flag FROM webloginlist w LEFT JOIN staff s ON s.staff_id = w.staff_id WHERE w.loginuuid = '" + token + "'", "dataSource");
        int pwd_flag = pwdflaglist[0].get("pwd_flag");
        log.info("[pwd_flag]：" + pwd_flag);
        if (pwd_flag == 1) {
            results.put("code", "1");
            results.put("msg", "密码校验不通过，重新修改");
        } else {
            results.put("code", "0");
            results.put("msg", "密码校验通过");
        }
        return results;
    }

    /**
     * 更新密码
     */
    public JSONObject updatePWD(EliteBean eliteBean, String token, String old_password, String new_password, String again_password) {
        JSONObject results = new JSONObject();
        String update_password = "";

        //系统使用密码何种加密方式，值为空不加密
        List ecTypeList = eliteBean.chaxun_sql("SELECT parametervalue FROM SYSC_PARAMETER WHERE ltrim(rtrim(upper( PARAMETER_ID )))= 'ECTYPE' ", "dataSource");
        String ecType = ecTypeList[0].get("parametervalue").toString();
        log.info("[系统参数配置加密方式ecType]：" + ecType);

        //将输入密码sm3加密后和现有密码做比较
        List oldpasswordlist = eliteBean.chaxun_sql("SELECT s.staff_id, s.password FROM webloginlist w LEFT JOIN staff s ON s.staff_id = w.staff_id WHERE w.loginuuid = '" + token + "'", "dataSource");
        String staffid = oldpasswordlist[0].get("staff_id").toString();
        String staffpwssword = oldpasswordlist[0].get("password").toString(); //staff表中的密码
        String staffPWDStyle = '';
        if(staffpwssword.length()>5){
            staffPWDStyle = staffpwssword.substring(0, 5); //截取staff表中的密码前5位，查看现有密码的加密方式
        }

        log.info("[staff表中的密码staffpwssword]：" + staffpwssword);
        log.info("[staff表中的密码加密方式staffPWDStyle]：" + staffPWDStyle);

        String SM3_oldpassword = "[SM3]" + encrypt(old_password);
        String SM3_newpassword = "[SM3]" + encrypt(new_password);
        String SM3_againpassword = "[SM3]" + encrypt(again_password);

        if (staffPWDStyle.equals("[SM3]")) { //SM3加密
            if (staffpwssword.equals(SM3_oldpassword)) {
                if (SM3_newpassword.equals(SM3_againpassword)) {
                    if (staffpwssword.equals(SM3_newpassword)) {
                        results.put("code", "-1");
                        results.put("msg", "密码校验不通过：新密码不能与旧密码一样");
                        return results;
                    }
                } else {
                    results.put("code", "-1");
                    results.put("msg", "密码校验不通过：新密码与确认密码不一致");
                    return results;
                }
            } else {
                results.put("code", "-1");
                results.put("msg", "密码校验不通过：旧密码输入错误");
                return results;
            }
            if (ecType.equals("SM3")) { //系统参数配置SM3加密
                update_password = SM3_newpassword;
            } else { //系统参数配置为空
                update_password = new_password;
            }

        } else { //明文密码
            if (staffpwssword.equals(old_password)) {
                if (new_password.equals(again_password)) {
                    if (staffpwssword.equals(new_password)) {
                        results.put("code", "-1");
                        results.put("msg", "密码校验不通过：新密码不能与旧密码一样");
                        return results;
                    }
                } else {
                    results.put("code", "-1");
                    results.put("msg", "密码校验不通过：新密码与确认密码不一致");
                    return results;
                }
            } else {
                results.put("code", "-1");
                results.put("msg", "密码校验不通过：旧密码输入错误");
                return results;
            }
            if (ecType.equals("SM3")) { //系统参数配置SM3加密
                update_password = SM3_newpassword;
            } else { //系统参数配置为空
                update_password = new_password;
            }
        }

        //查询系统参数中配置的密码复杂度：为空就忽略，参数格式为: 最小长度,密码强度，能否为空，过期天数； 最小长度：密码长度的最短限制。 密码强度：密码复杂度等级设置，规则如下： 0=普通密码； 1=必须包括大小写字母； 2=必须包括数字； 3=必须包括特殊字符； 4=不允许使用连续相邻4个或以上的字母及数字； 5=不允许使用键盘连续相邻4个或以上的字母及数字； 注：强度等级高的包含强度等级低的规则要求。
        List custlist = eliteBean.chaxun_sql("SELECT parametervalue FROM SYSC_PARAMETER WHERE ltrim(rtrim(upper( PARAMETER_ID )))= 'PWDRUL' ", "dataSource");
        String parametervalue = custlist[0].get("parametervalue").toString();
        log.info("[parametervalue]：" + parametervalue);

        if (KHUtil.isNull(parametervalue)) { //没有配置密码复杂度直接通过
            eliteBean.update("UPDATE staff SET PASSWORD = '" + update_password + "', pwd_flag = 0, MODIFIEDBY = '" + staffid + "', MODIFIEDDATE = SYSDATE() WHERE staff_id = '" + staffid + "' ", "dataSource");
            results.put("code", "0");
            results.put("msg", "密码校验通过：已更新密码");
        } else {
            String[] parametervalues = parametervalue.split(",");
            int pwdlength = Integer.parseInt(parametervalues[0]);//最小长度

            if (new_password.length() < pwdlength) {
                results.put("code", "-1");
                results.put("msg", "密码校验不通过：密码长度不能小于" + pwdlength);
            } else {
                if (parametervalues.length >= 2) {
                    int pwdstrength = Integer.parseInt(parametervalues[1]);//密码强度
                    log.info("[密码强度pwdstrength]：" + pwdstrength);

                    if (pwdstrength == 0) { //0=普通密码
                        eliteBean.update("UPDATE staff SET PASSWORD = '" + update_password + "', pwd_flag = 0, MODIFIEDBY = '" + staffid + "', MODIFIEDDATE = SYSDATE() WHERE staff_id = '" + staffid + "' ", "dataSource");
                        results.put("code", "0");
                        results.put("msg", "密码校验通过：已更新密码");
                    } else if (pwdstrength == 1) { //1=必须包括大小写字母
                        results = checkLetter(new_password);
                        if (results.code == "0") {
                            eliteBean.update("UPDATE staff SET PASSWORD = '" + update_password + "', pwd_flag = 0, MODIFIEDBY = '" + staffid + "', MODIFIEDDATE = SYSDATE()  WHERE staff_id = '" + staffid + "' ", "dataSource");
                            return results;
                        } else {
                            return results;
                        }
                    } else if (pwdstrength == 2) { //2=必须包括数字
                        results = checkLetter(new_password);
                        if (results.code == "0") {
                            Pattern number = Pattern.compile(".*[0-9].*");
                            boolean num = number.matcher(new_password).matches();
                            log.info("[校验密码中是否包括数字num]：" + num);
                            if (num) {
                                eliteBean.update("UPDATE staff SET PASSWORD = '" + update_password + "', pwd_flag = 0, MODIFIEDBY = '" + staffid + "', MODIFIEDDATE = SYSDATE()  WHERE staff_id = '" + staffid + "' ", "dataSource");
                                results.put("code", "0");
                                results.put("msg", "密码校验通过：已更新密码");
                            } else {
                                results.put("code", "-1");
                                results.put("msg", "密码校验不通过：必须包括数字");
                            }
                        } else {
                            return results;
                        }
                    }
                }
            }
        }
        return results;
    }

    /**
     * 校验密码中是否包括大小写字母
     */
    public JSONObject checkLetter(String password) {
        JSONObject results = new JSONObject();
        Pattern bigLetter = Pattern.compile(".*[A-Z].*");
        Pattern smallLetter = Pattern.compile(".*[a-z].*");
        boolean bin = bigLetter.matcher(password).matches();
        boolean small = smallLetter.matcher(password).matches();
        log.info("[BIG]：" + bin + "；[SMALL]：" + small);
        if (bin && small) {
            results.put("code", "0");
            results.put("msg", "密码校验通过");
        } else {
            results.put("code", "-1");
            results.put("msg", "密码校验不通过：必须包括大小写字母");
        }
        log.info("[校验密码中是否包括大小写字母results]：" + results);
        return results;
    }

    /**
     * sm3算法加密
     * @param paramStr 待加密字符串
     * @return 返回加密后，固定长度=32的16进制字符串
     */
    public static String encrypt(String paramStr) {
        // 将返回的hash值转换成16进制字符串
        String ENCODING = "UTF-8";
        String resultHexString = "";
        try {
            // 将字符串转换成byte数组
            byte[] srcData = paramStr.getBytes(ENCODING);
            // 调用hash()
            byte[] resultHash = hash(srcData);
            // 将返回的hash值转换成16进制字符串
            resultHexString = ByteUtils.toHexString(resultHash);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return resultHexString;
    }

    /**
     * 返回长度=32的byte数组
     */
    public static byte[] hash(byte[] srcData) {
        SM3Digest digest = new SM3Digest();
        digest.update(srcData, 0, srcData.length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash, 0);
        return hash;
    }
}